package com.gzc.just.play.server;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * IPPool类的作用<p>
 * IPPool类是一个IP地址池管理器，专门用于管理和分配虚拟IP地址。在Warcraft III连接系统中，每个连接到服务器的客户端都需要被分配一个唯一的虚拟IP地址，
 * 以便其他客户端能够识别和连接到它。IPPool负责生成、分配和回收这些虚拟IP地址。<p>
 *
 * 工作流程<p>
 * 1.初始化：在创建IPPool实例时，会调用initializeIPs()方法生成一个IP地址池，包含从127.0.1.1到127.0.1.255的255个IP地址。<p>
 * 2.分配IP：<p>
 * 当有新的客户端连接时，服务器调用acquireIP()方法从池中获取一个可用的IP地址.<p>
 * 这个IP地址会分配给该客户端作为其虚拟IP.<p>
 * 3.释放IP：<p>
 * 当客户端断开连接时，服务器调用releaseIP()方法将该客户端的IP地址返回到池中.<p>
 * 这样该IP地址可以被后续连接的客户端重新使用.<p>
 *
 * 算法说明<p>
 * IPPool类使用了以下算法和数据结构：<p>
 * 1.数据结构：<p>
 * 使用LinkedBlockingQueue<String>作为核心数据结构存储可用的IP地址.<p>
 * 这是一个线程安全的阻塞队列，适合在多线程环境中使用.<p>
 * 2.IP生成算法：initializeIPs方法<p>
 * 3.IP分配算法：<p>
 *     acquireIP()：使用take()方法阻塞式地从队列头部取出一个IP地址.<p>
 *     tryAcquireIP()：使用poll()方法非阻塞地尝试获取一个IP地址.<p>
 * 4.IP回收算法：releaseIP方法<p>
 * 5.验证算法：<p>
 * 使用正则表达式^127\\.0\\.1\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$验证IP地址是否在合法范围内：<p>
 * 25[0-5]匹配250-255<p>
 * 2[0-4][0-9]匹配200-249<p>
 * [01]?[0-9][0-9]?匹配0-199<p>
 *
 * 这种设计确保了IP地址的有效管理，避免了IP地址冲突，并且能够高效地分配和回收IP地址资源。
 */
public class IPPool {
    private final BlockingQueue<String> availableIPs;

    public IPPool() {
        this.availableIPs = new LinkedBlockingQueue<>();
        initializeIPs();
    }

    private void initializeIPs() {
        // 使用简单的循环生成255个IP地址（127.0.1.1到127.0.1.255），并将它们添加到队列中。
        for (int i = 1; i <= 255; i++) {
            availableIPs.add("127.0.1." + i);
        }
    }

    /**
     * 获取一个可用IP
     *
     * @return IP地址字符串
     * @throws InterruptedException 如果等待时被中断
     */
    public String acquireIP() throws InterruptedException {
        return availableIPs.take(); // 阻塞直到有可用IP
    }

    /**
     * 释放IP地址，将其返回到池中
     *
     * @param ip 要释放的IP地址
     */
    public void releaseIP(String ip) {
        // 首先验证IP地址格式是否符合要求（127.0.1.x范围）
        // 然后将IP地址添加回队列尾部，供后续使用
        if (ip != null && ip.matches("^127\\.0\\.1\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$")) {
            availableIPs.add(ip);
        }
    }

    /**
     * 尝试获取IP（非阻塞）
     *
     * @return 可用IP或null（如果没有可用IP）
     */
    public String tryAcquireIP() {
        return availableIPs.poll();
    }

    /**
     * 获取当前可用IP数量
     *
     * @return 可用IP数量
     */
    public int availableIPCount() {
        return availableIPs.size();
    }
}